﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace Nature.Numerics
{
    public static class Utilities
    {
        public static Guid CalcMD5Hash(IEnumerable<string> stringsCollection)
        {
            MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider();
            var bytes =
                from s in stringsCollection
                from b in Encoding.Unicode.GetBytes(s)
                select b;
            return new Guid(provider.ComputeHash(bytes.ToArray()));
        }

        public static T[][] CreateMatrix<T>(int iLength) where T : new()
        {
            return CreateMatrix<T>(iLength, i => iLength);
        }

        public static T[][] CreateMatrix<T>(int iLength, int jLength) where T : new()
        {
            return CreateMatrix<T>(iLength, i => jLength);
        }

        public static T[][] CreateMatrix<T>(int iLength, Func<int, int> getJLength) where T : new()
        {
            T[][] matrix = new T[iLength][];
            for (int i = 0; i < iLength; ++i)
            {
                matrix[i] = new T[getJLength(i)];
            }
            return matrix;
        }

        public static double RelativeDifference(double val1, double val2)
        {
            double averaged = 0.5 * (val1 + val2);
            averaged += averaged < 0.0 ? (-double.Epsilon) : (+double.Epsilon);
            return (val2 - val1) / averaged;
        }

        public static double AbsRelativeDifference(double val1, double val2)
        {
            return Math.Abs(RelativeDifference(val1, val2));
        }

        public static double Factorial(int p)
        {
            double result = p;
            while (--p > 1)
            {
                result *= p;
            }
            return result;
        }
    }
}
